defIconFunction <-
  JS("function(icon){
        if (!$.isEmptyObject(icon)) {
          return L.icon(icon);
        } else {
          return L.icon();
        }
     }")

awesomeIconFunction <-
  JS("function(icon){
        if (!$.isEmptyObject(icon)) {
          if (!icon.prefix) {
            icon.prefix = icon.library;
          }
          return L.AwesomeMarkers.icon(icon);
        } else {
          return L.AwesomeMarkers.icon();
        }
     }")

#' Converts GeoJSON Feature properties to HTML
#' @param props A list of GeoJSON Property Keys.
#' @param elem An optional wrapping element e.g. "div".
#' @param elem.attrs An optional named list for the wrapper element properties.
#' @export
#' @rdname utils
propsToHTML <- function(props, elem = NULL, elem.attrs = NULL) {
  if (!(inherits(props, "list") || (class(props) == "character")) ||  length(props) < 1 ) {
    stop("props needs to to be a list/vector of character strings with at least one element")
  }
  if (!is.null(elem.attrs) &&
     (!inherits(elem.attrs, "list") ||
      length(elem.attrs) < 1 ||
      is.null(names(elem.attrs)))) {
    stop("If elem.attrs is provided, then it needs to be a named list with atleast one element")
  }
  JS(sprintf(
    "function(feature){return \"%s\" + L.Util.template(\"%s\",feature.properties); + \"%s\";}",
    if (!is.null(elem) && !elem == "")
      sprintf("<%s%s>",
              elem,
              if (!is.null(elem.attrs))
                paste(sapply(names(elem.attrs),
                             function(attr) sprintf(" %s=\"%s\"", attr, elem.attrs[[attr]])), collapse = " ")
              else
                "" )
    else
      "",
    if (length(props) > 1)
      paste(stringr::str_replace(props, "(.*)", "{\\1}"), collapse = ", ")
    else
      props,
    if (!is.null(elem) && !elem == "")
      sprintf("</%s>", elem)
    else
      ""
    ))
}

#' Converts GeoJSON Feature properties to HTML Table.
#' @param table.attrs An optional named list for the HTML Table.
#' @param drop.na whether to skip properties with empty values.
#' @export
#' @rdname utils
propstoHTMLTable <- function(props = NULL, table.attrs = NULL, drop.na = TRUE) {
  if (!is.null(table.attrs) &&
     (!inherits(table.attrs, "list") ||
      length(table.attrs) < 1 ||
      is.null(names(table.attrs)))) {
    stop("If table.attrs is provided, then it needs to be a named list with at least one element")
  }

  if (!is.null(props) && length(props) >= 1)
    JS(sprintf(
      "function(feature){
         return '<table%s><caption>Properties</caption><tbody style=\"font-size:x-small\">' +
           ( $.isEmptyObject(feature.properties) ? '' :
             L.Util.template(\"%s\",feature.properties)
           )+ \"</tbody></table>\";
       }",
      if (!is.null(table.attrs))
        paste(sapply(names(table.attrs),
                     function(attr) sprintf(" %s=\"%s\"", attr, table.attrs[[attr]])), collapse = " ")
      else "",
      paste(stringr::str_replace(props, "(.*)", "<tr><td><b>\\1</b></td><td>{\\1}</td></tr>"), collapse = "")
    ))
  else
   JS(sprintf(
     "function(feature){
        return '<table%s><caption>Properties</caption><tbody style=\"font-size:x-small\">' +
          ( function(props) {
            var rws = '';
            $.each(props, function (k, v) {
              if ( %s ||(v !== null && typeof v !== \"undefined\")) {
                rws = rws.concat(\"<tr><td><b>\"+k+\"</b></td><td>\"+
                ((v !== null && typeof v !== \"undefined\") ? v : '') +
                \"</td></tr>\");
              }
            });
            return rws;
          })(feature.properties) + \"</tbody></table>\";}",
     if (!is.null(table.attrs))
       paste(sapply(names(table.attrs),
                    function(attr) sprintf(" %s=\"%s\"", attr, table.attrs[[attr]])), collapse = " ")
     else "",
     if (drop.na) "false" else "true"
    ))

}
